package com.huatai.vba.file.dbf;

import java.io.*;
import java.sql.*;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.linuxense.javadbf.*;

public class DBFUtils {

	private static final Logger logger = LoggerFactory.getLogger(DBFUtils.class);

	public static DBFField[] generateDBFField(String[] strutName, byte[] strutType, int[] strutLength) {
		int fieldCount = strutName.length;
		DBFField[] fields = new DBFField[fieldCount];

		for (int i = 0; i < fieldCount; i++) {
			fields[i] = new DBFField();
			fields[i].setName(strutName[i]);
			fields[i].setDataType(strutType[i]);

			if (DBFField.FIELD_TYPE_D != strutType[i]) {
				fields[i].setFieldLength(strutLength[i]);
			}
		}
		return fields;
	}

	public static void generateDbfFromArray(String fileName, String[] strutName, byte[] strutType, int[] strutLength,
			Object[][] data) throws Exception {
		DBFField[] fields = generateDBFField(strutName, strutType, strutLength);

		DBFObject object = new DBFObject(fileName, fields, data);
		generateDBF(object);
	}

	public static void generateDBF(DBFObject dbfObject) throws Exception {
		for (DBFField f : dbfObject.getFields()) {
			if (StringUtils.startsWithIgnoreCase(f.getName(), "dbf_")) {
				f.setName(f.getName().substring(3));
			}
		}
		DBFWriter writer = new DBFWriter(new File(dbfObject.getFileName()));
		writer.setFields(dbfObject.getFields());
		Object[] data = dbfObject.getData();
		if (data != null && data.length != 0) {
			for (int i = 0; i < data.length; i++) {
				writer.addRecord((Object[]) data[i]);
			}
		}
		writer.write();
	}

	public static void ResultsetToArray(String path, String fileName, ResultSet rs) throws Exception {
		ResultSetMetaData meta = rs.getMetaData();
		int columnCount = meta.getColumnCount();

		String[] strutName = new String[columnCount];
		int[] strutLength = new int[columnCount];
		byte[] strutType = new byte[columnCount];
		rs.last();
		int itemCount = rs.getRow();

		rs.beforeFirst();
		Object[][] data = new Object[itemCount][columnCount];
		for (int i = 0; i < columnCount; i++) {
			strutType[i] = fieldType((byte) meta.getColumnType(i + 1));
			strutName[i] = meta.getColumnName(i + 1);
			if (DBFField.FIELD_TYPE_D != strutType[i]) {
				strutLength[i] = meta.getColumnDisplaySize(i + 1);
			}
		}
		for (int i = 0; rs.next(); i++) {
			for (int j = 0; j < columnCount; j++) {
				data[i][j] = rs.getObject(j + 1);
			}
		}
		generateDbfFromArray(path + "\\" + fileName, strutName, strutType, strutLength, data);
	}

	/*
	 * String dbfType
	 */
	public static byte fieldType(byte jdbcType) {
		if (Types.VARCHAR == jdbcType) {
			return DBFField.FIELD_TYPE_C;
		} else if (Types.INTEGER == jdbcType || Types.NUMERIC == jdbcType || Types.DATALINK == jdbcType) {
			return DBFField.FIELD_TYPE_F;
		} else if (Types.DATE == jdbcType) {
			return DBFField.FIELD_TYPE_D;
		}
		return DBFField.FIELD_TYPE_C;
	}

	public static boolean isNumber(byte jdbcType) {

		// 数字型
		if (DBFField.FIELD_TYPE_N == jdbcType || DBFField.FIELD_TYPE_F == jdbcType) {
			return true;
		}
		return false;
	}

	public static DBFObject readDBF(String fileName) throws Exception {
		return readDBF(fileName, "GB2312");
	}

	/**
	 * 将dbf文件封装成List<String>
	 *
	 * @param filePath
	 *            DBF文件路径
	 * @param fileName
	 *            读取DBF文件名
	 * @param readFileEnCode
	 *            设置读取文件编码格式 默认GB2312
	 * @return dbf文件封装后List<String>对象
	 */
	public static DBFObject readDBF(String fileName, String readFileEnCode) throws Exception {
		InputStream inputStream = null;
		Object[] rowObjects = null;
		DBFField[] fields = null;
		List<Object[]> data = null;
		DBFObject object = null;
		try {
			data = Lists.newArrayList();
			inputStream = new FileInputStream(fileName);
			DBFReader reader = new DBFReader(inputStream);
			reader.setCharactersetName(readFileEnCode);
			int fieldCount = reader.getFieldCount();
			fields = new DBFField[fieldCount];
			while ((rowObjects = reader.nextRecord()) != null) {
				data.add(rowObjects);
				if (fields[0] != null)
					continue;
				for (int i = 0; i < fieldCount; i++) {
					fields[i] = reader.getField(i);
					String name = fields[i].getName();
					if ("by".equalsIgnoreCase(name)) {
						fields[i].setName("dbf_" + name);
					}
				}
			}
			object = new DBFObject(fileName, fields, data.toArray());
		} catch (FileNotFoundException fe) {
			throw fe;
		} catch (Exception ex) {
			throw ex;
		} finally {
			if (null != inputStream) {
				try {
					inputStream.close();
				} catch (IOException ex) {
					throw ex;
				}
			}
		}
		return object;
	}

	public static void clearDBF(String fileName) throws Exception {
		// 需要優化
		logger.info("clearDBF:{}", fileName);
		File f = new File(fileName);
		if (f.exists()) {
			DBFObject dbfObject = readDBF(fileName);
			f.delete();
			dbfObject.setData(null);
			generateDBF(dbfObject);
		} else
			logger.info("无文件:{}", fileName);
	}

}
